package com.it.filter;

import cn.hutool.core.util.StrUtil;
import com.it.entity.SysUser;
import com.it.service.SysUserService;
import com.it.service.impl.UserDetailsServiceImpl;
import com.it.utisl.JwtUtils;
import com.it.utisl.RedisUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.TreeSet;

/**
 * TODO
 *
 * @author: Coke
 * @DateTime: 2023/11/19/20:05
 **/
@Slf4j
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    
    @Autowired
    SysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    
    // 构造方法，接收 AuthenticationManager
    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
    
    @Override
    // 进行JWT校验的过滤操作
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 日志记录JWT校验过滤器的执行
        log.info("JWT校验过滤器执行");
        
        // 从请求头中获取JWT
        String jwt = request.getHeader(jwtUtils.getHeader());
        
        // 如果JWT为空，则直接放行，继续处理下一个过滤器
        if (StrUtil.isBlankOrUndefined(jwt)) {
            chain.doFilter(request, response);
            return;
        }
        
        // 使用JWT工具类解析JWT获取声明
        Claims claim = jwtUtils.getClaimByToken(jwt);
        
        // 如果JWT异常，则抛出JwtException
        if (claim == null) {
            throw new JwtException("Token异常");
        }
        
        // 如果JWT已过期，则抛出JwtException
        if (jwtUtils.isTokenExpired(claim)) {
            throw new JwtException("Token已过期");
        }
        
        // 从JWT中获取用户名
        String username = claim.getSubject();
        
        // 日志记录正在登录的用户信息
        log.info("用户-{}，正在登录！", username);
    
        SysUser sysUser = sysUserService.getByUsername(username);
        UsernamePasswordAuthenticationToken token
              = new UsernamePasswordAuthenticationToken(username, null, userDetailsService.getUserAuthority(sysUser.getId()));
    
        // 将认证信息设置到安全上下文中
        SecurityContextHolder.getContext().setAuthentication(token);
        
        // 继续处理请求
        chain.doFilter(request, response);
    }
}
